using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using RTMP.SimpleClient.Helpers;

namespace RTMP.SimpleClient.Helpers
{
    /// <summary>
    /// RTMP 命令助手类
    /// </summary>
    public static class RTMPCommandHelper
    {
        #region 通用命令构建接口

        /// <summary>
        /// 创建命令头部（命令名 + 事务ID）
        /// </summary>
        /// <param name="commandName">命令名</param>
        /// <param name="transactionId">事务ID</param>
        /// <returns>AMF0编码的命令头部</returns>
        public static byte[] CreateCommandHeader(string commandName, double transactionId)
        {
            // 命令名
            var commandBytes = AMF0Helper.Encode(commandName);

            // 事务ID
            var transactionBytes = AMF0Helper.Encode(transactionId);

            // 组合头部
            var result = new byte[commandBytes.Length + transactionBytes.Length];
            Array.Copy(commandBytes, 0, result, 0, commandBytes.Length);
            Array.Copy(transactionBytes, 0, result, commandBytes.Length, transactionBytes.Length);
            return result;
        }

        /// <summary>
        /// 创建命令体（参数对象）
        /// </summary>
        /// <param name="parameters">参数数组</param>
        /// <returns>AMF0编码的命令体</returns>
        public static byte[] CreateCommandBody(params object?[] parameters)
        {
            using (var ms = new MemoryStream())
            using (var writer = new BinaryWriter(ms))
            {
                foreach (var param in parameters)
                {
                    // 使用原来的 byte[] 版本的 Encode 方法
                    var paramBytes = AMF0Helper.Encode(param);
                    writer.Write(paramBytes);
                }

                return ms.ToArray();
            }
        }

        /// <summary>
        /// 组合头部和体部返回完整的数据包
        /// </summary>
        /// <param name="header">命令头部</param>
        /// <param name="body">命令体</param>
        /// <returns>完整的AMF0命令数据包</returns>
        public static byte[] CombineHeaderAndBody(byte[] header, byte[] body)
        {
            var result = new byte[header.Length + body.Length];
            Array.Copy(header, 0, result, 0, header.Length);
            Array.Copy(body, 0, result, header.Length, body.Length);
            return result;
        }

        #endregion

        #region 直接创建命令包接口

        /// <summary>
        /// 创建 connect 命令完整数据包
        /// </summary>
        /// <param name="app">应用名</param>
        /// <param name="tcUrl">完整URL</param>
        /// <param name="flashVer">Flash版本</param>
        /// <param name="transactionId">事务ID</param>
        /// <returns>完整的connect命令数据包</returns>
        public static byte[] CreateConnectCommandPacket(string app, string tcUrl, string flashVer = "FMLE/3.0 (compatible; FMSc/1.0)", double transactionId = 1.0)
        {
            Span<byte> buffer = stackalloc byte[1024];

            var header = CreateCommandHeader("connect", transactionId);

            var commandObject = new Dictionary<string, object>
            {
                ["app"] = app,
                ["flashVer"] = flashVer,
                ["tcUrl"] = tcUrl,
                ["fpad"] = false,
                ["capabilities"] = 15.0,
                ["audioCodecs"] = 3191.0,
                ["videoCodecs"] = 252.0,
                ["videoFunction"] = 1.0
            };

            var body = CreateCommandBody(commandObject);
            return CombineHeaderAndBody(header, body);
        }

        /// <summary>
        /// 创建 createStream 命令完整数据包
        /// </summary>
        /// <param name="transactionId">事务ID</param>
        /// <returns>完整的createStream命令数据包</returns>
        public static byte[] CreateCreateStreamCommandPacket(double transactionId = 2.0)
        {
            var header = CreateCommandHeader("createStream", transactionId);
            var body = CreateCommandBody((object?)null); // createStream命令只需要一个null参数
            return CombineHeaderAndBody(header, body);
        }

        /// <summary>
        /// 创建 setChunkSize 命令完整数据包
        /// </summary>
        /// <param name="chunkSize">新的分块大小</param>
        /// <param name="transactionId">事务ID</param>
        /// <returns>完整的setChunkSize命令数据包</returns>
        public static byte[] CreateSetChunkSizeCommandPacket(int chunkSize, double transactionId = 0.0)
        {
            var header = CreateCommandHeader("setChunkSize", transactionId);
            var body = CreateCommandBody(null, chunkSize);
            return CombineHeaderAndBody(header, body);
        }

        /// <summary>
        /// 创建 play 命令完整数据包
        /// </summary>
        /// <param name="streamName">流名称</param>
        /// <param name="transactionId">事务ID</param>
        /// <returns>完整的play命令数据包</returns>
        public static byte[] CreatePlayCommandPacket(string streamName, double transactionId = 0.0)
        {
            var header = CreateCommandHeader("play", transactionId);
            var body = CreateCommandBody(null, streamName);
            return CombineHeaderAndBody(header, body);
        }

        /// <summary>
        /// 创建 publish 命令完整数据包
        /// </summary>
        /// <param name="streamName">流名称</param>
        /// <param name="publishType">发布类型</param>
        /// <param name="transactionId">事务ID</param>
        /// <returns>完整的publish命令数据包</returns>
        public static byte[] CreatePublishCommandPacket(string streamName, string publishType = "live", double transactionId = 0.0)
        {
            var header = CreateCommandHeader("publish", transactionId);
            var body = CreateCommandBody(null, streamName, publishType);
            return CombineHeaderAndBody(header, body);
        }

        #endregion

        #region 向下兼容的原有接口
        /// <summary>
        /// 创建 connect 命令（向下兼容接口）
        /// </summary>
        /// <param name="app">应用名</param>
        /// <param name="tcUrl">完整URL</param>
        /// <param name="flashVer">Flash版本</param>
        /// <returns>AMF0编码的命令数据</returns>
        public static byte[] CreateConnectCommand(string app, string tcUrl, string flashVer = "FMLE/3.0 (compatible; FMSc/1.0)")
        {
            return CreateConnectCommand(app, tcUrl, flashVer, 1.0);
        }

        /// <summary>
        /// 创建带指定事务ID的 connect 命令（向下兼容接口）
        /// </summary>
        /// <param name="app">应用名</param>
        /// <param name="tcUrl">完整URL</param>
        /// <param name="flashVer">Flash版本</param>
        /// <param name="transactionId">事务ID</param>
        /// <returns>AMF0编码的命令数据</returns>
        public static byte[] CreateConnectCommand(string app, string tcUrl, string flashVer, double transactionId)
        {
            // 调用新的直接创建接口
            return CreateConnectCommandPacket(app, tcUrl, flashVer, transactionId);
        }

        /// <summary>
        /// 创建 createStream 命令（向下兼容接口）
        /// </summary>
        /// <returns>AMF0编码的命令数据</returns>
        public static byte[] CreateCreateStreamCommand()
        {
            return CreateCreateStreamCommand(2.0);
        }

        /// <summary>
        /// 创建带指定事务ID的 createStream 命令（向下兼容接口）
        /// </summary>
        /// <param name="transactionId">事务ID</param>
        /// <returns>AMF0编码的命令数据</returns>
        public static byte[] CreateCreateStreamCommand(double transactionId)
        {
            // 调用新的直接创建接口
            return CreateCreateStreamCommandPacket(transactionId);
        }

        /// <summary>
        /// 创建 play 命令（向下兼容接口）
        /// </summary>
        /// <param name="streamName">流名称</param>
        /// <returns>AMF0编码的命令数据</returns>
        public static byte[] CreatePlayCommand(string streamName)
        {
            // 调用新的直接创建接口
            return CreatePlayCommandPacket(streamName, 0.0);
        }

        /// <summary>
        /// 创建 publish 命令（向下兼容接口）
        /// </summary>
        /// <param name="streamName">流名称</param>
        /// <param name="publishType">发布类型</param>
        /// <returns>AMF0编码的命令数据</returns>
        public static byte[] CreatePublishCommand(string streamName, string publishType = "live")
        {
            // 调用新的直接创建接口
            return CreatePublishCommandPacket(streamName, publishType, 0.0);
        }

        #endregion

        #region 命令解析功能

        /// <summary>
        /// 解析命令响应
        /// </summary>
        /// <param name="data">响应数据</param>
        /// <returns>解析后的命令响应</returns>
        public static RTMPCommandResponse ParseCommandResponse(byte[] data)
        {
            var response = new RTMPCommandResponse();

            try
            {
                using (var ms = new MemoryStream(data))
                using (var reader = new BinaryReader(ms))
                {
                    // 解析命令名
                    response.CommandName = DecodeAMF0Value(reader) as string;

                    // 解析事务ID
                    var transactionIdObj = DecodeAMF0Value(reader);
                    response.TransactionId = transactionIdObj is double d ? d : 0.0;

                    // 解析命令对象
                    response.CommandObject = DecodeAMF0Value(reader);

                    // 如果还有更多数据，解析附加信息
                    if (reader.BaseStream.Position < reader.BaseStream.Length)
                    {
                        response.AdditionalInfo = DecodeAMF0Value(reader);
                    }
                }
            }
            catch (Exception ex)
            {
                response.ParseError = ex.Message;
            }

            return response;
        }

        /// <summary>
        /// 解码单个AMF0值（使用AMF0Helper的私有方法）
        /// </summary>
        private static object? DecodeAMF0Value(BinaryReader reader)
        {
            // 使用反射调用AMF0Helper的私有DecodeValue方法
            var method = typeof(AMF0Helper).GetMethod("DecodeValue", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
            if (method != null)
            {
                return method.Invoke(null, new object[] { reader }) as object;
            }

            // 备选方案：简单实现
            var type = reader.ReadByte();
            switch (type)
            {
                case 0x02: // String
                    var length = reader.ReadUInt16();
                    var bytes = reader.ReadBytes(length);
                    return Encoding.UTF8.GetString(bytes);
                case 0x00: // Number
                    return reader.ReadDouble();
                case 0x05: // Null
                    return null;
                default:
                    return null;
            }
        }

        /// <summary>
        /// 解析 createStream 命令响应
        /// </summary>
        /// <param name="data">响应数据</param>
        /// <returns>新创建的流ID，如果解析失败则返回null</returns>
        public static uint? ParseCreateStreamResponse(byte[] data)
        {
            var response = ParseCommandResponse(data);

            // 检查是否是成功的响应
            if (response.CommandName == "_result" && response.TransactionId == 2.0)
            {
                // AdditionalInfo 应该包含流ID
                if (response.AdditionalInfo is double streamIdDouble)
                {
                    return (uint)streamIdDouble;
                }
            }

            return null;
        }

        /// <summary>
        /// RTMP 命令响应结构
        /// </summary>
        public class RTMPCommandResponse
        {
            public string? CommandName { get; set; }
            public double TransactionId { get; set; }
            public object? CommandObject { get; set; }
            public object? AdditionalInfo { get; set; }
            public string? ParseError { get; set; }
        }

        #endregion
    }
}
